package com.yanqu.road.server.manager.tomb.entity;

import com.yanqu.road.dao.dbV2.BaseEntity;
import com.yanqu.road.dao.dbV2.IField;
import com.yanqu.road.dao.dbV2.ITable;
import com.yanqu.road.dao.dbV2.serializer.*;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

@ITable(tableName = "t_c_activity_tomb_position")

public class DbTombPosition extends BaseEntity {
    public static DbTombPosition newInstance() {
        return new DbTombPosition();
    }

    private final Lock lock =  new ReentrantLock();

    @IField(isPrimaryKey = true, fieldName = "activity_id", serializer = DInt.class)
    public int activityId;

    @IField(isPrimaryKey = true, fieldName = "groupId", serializer = DInt.class)
    public int groupId;

    @IField(isPrimaryKey = true, fieldName = "floor", serializer = DInt.class)
    public int floor;

    @IField(isPrimaryKey = true, fieldName = "done", serializer = DInt.class)
    public int done;

    @IField(isPrimaryKey = true, fieldName = "x", serializer = DInt.class)
    public int x;
    @IField(isPrimaryKey = true, fieldName = "y", serializer = DInt.class)
    public int y;
    @IField(fieldName = "p_enum", serializer = DInt.class)
    public int pEnum;

    @IField(fieldName = "finish_user_id", comment = "事件完成者", serializer = DLong.class)
    public long finishUserId;

    @IField(fieldName = "event_id", comment = "事件id", serializer = DInt.class)
    public int eventId;

    @IField(fieldName = "e_type", comment = "事件类型", serializer = DInt.class)
    public int eType;

    @IField(fieldName = "max_hp", comment = "最高血量", serializer = DLong.class)
    public long maxHp;

    @IField(fieldName = "current_hp", comment = "当前血量", serializer = DLong.class)
    public long currentHp;

    @IField(fieldName = "over_time", comment = "事件结束时间", serializer = DDateTime.class)
    public long overTime = 0;

    @IField(fieldName = "event_info_map", comment = "事件信息详情", serializer = DObject.class)
    public Map<Long, PositionInfo> eventInfoMap = new ConcurrentHashMap<>();

    @IField(fieldName = "pvp_user_id", comment = "pvp选择人员", serializer = DLong.class)
    public long pvpUserId;

    @IField(fieldName = "help_user_id_list", comment = "帮助人员", serializer = DObject.class)
    public Set<Long> helpUserIdList = new HashSet<>();

    @IField(fieldName = "is_send_help", comment = "是否已发送求救", serializer = DInt.class)
    public int isSendHelp;

    @IField(fieldName = "dig_union_user_map", comment = "发现者信息", serializer = DObject.class)
    public Map<String, DigUserInfo> digUnionUserMap = new ConcurrentHashMap<>();

    @IField(fieldName = "status", comment = "事件状态", serializer = DInt.class)
    public int status;

    Map<Long,Long> operationTimeMap = new ConcurrentHashMap<>();

    public int getActivityId() {
        return activityId;
    }

    public void setActivityId(int activityId) {
        this.activityId = activityId;
    }

    public int getFloor() {
        return floor;
    }

    public void setFloor(int floor) {
        this.floor = floor;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getpEnum() {
        return pEnum;
    }

    public void setpEnum(int pEnum) {
        this.pEnum = pEnum;
    }

    public String getKey() {
        return String.format("%d_%d_%d", this.floor, this.x, this.y);
    }

    public int geteType() {
        return eType;
    }

    public void seteType(int eType) {
        this.eType = eType;
    }


    public int getEventId() {
        return eventId;
    }

    public void setEventId(int eventId) {
        this.eventId = eventId;
    }

    public long getMaxHp() {
        return maxHp;
    }

    public void setMaxHp(long maxHp) {
        this.maxHp = maxHp;
    }

    public long getCurrentHp() {
        if (this.currentHp < 0) {
            return 0;
        }
        return currentHp;
    }

    public void setCurrentHp(long currentHp) {
        this.currentHp = currentHp;
    }

    public int getDone() {
        return done;
    }

    public void setDone(int done) {
        this.done = done;
    }

    public long getOverTime() {
        return overTime;
    }

    public void setOverTime(long overTime) {
        this.overTime = overTime;
    }

    public long getFinishUserId() {
        return finishUserId;
    }

    public void setFinishUserId(long finishUserId) {
        this.finishUserId = finishUserId;
    }

    public Map<Long, PositionInfo> getEventInfoMap() {
        return eventInfoMap;
    }

    public void setEventInfoMap(Map<Long, PositionInfo> eventInfoMap) {
        this.eventInfoMap = eventInfoMap;
    }


    public void addEventInfo(long userId, String name, long value) {
        PositionInfo positionInfo = this.eventInfoMap.get(userId);
        if (positionInfo == null) {
            positionInfo = new PositionInfo();
            positionInfo.setUserId(userId);
        }
        positionInfo.setAttack(positionInfo.getAttack() + value);
        positionInfo.setAttackTimes(positionInfo.getAttackTimes() + 1);
        positionInfo.setTimestamp(Instant.now().getEpochSecond());
        this.eventInfoMap.put(userId, positionInfo);
    }

    public long underAttack(long attack) {
        long realAttack = this.currentHp;
        this.currentHp = this.currentHp - attack;
        if (this.currentHp <= 0) {
            this.currentHp = 0;
            return realAttack;
        }
        return attack;
    }

    public boolean isAlive() {
        if (this.currentHp <= 0) {
            return false;
        }
        return true;
    }

    public int getAttackTimes(long userId) {
        PositionInfo positionInfo = this.eventInfoMap.get(userId);
        if (positionInfo != null) {
            return (int) positionInfo.getAttackTimes();
        }
        return 0;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public long getPvpUserId() {
        return pvpUserId;
    }

    public void setPvpUserId(long pvpUserId) {
        this.pvpUserId = pvpUserId;
    }

    public Set<Long> getHelpUserIdList() {
        return helpUserIdList;
    }

    public void setHelpUserIdList(Set<Long> helpUserIdList) {
        this.helpUserIdList = helpUserIdList;
    }

    public int getIsSendHelp() {
        return isSendHelp;
    }

    public void setIsSendHelp(int isSendHelp) {
        this.isSendHelp = isSendHelp;
    }

    public synchronized void addUnionDigUser(String unionUid, long digUserid) {
        if (this.digUnionUserMap.containsKey(unionUid)) {
            return;
        }

        DigUserInfo digUserInfo = new DigUserInfo();
        digUserInfo.setUserId(digUserid);
        if (this.digUnionUserMap.size() == 0) {
            digUserInfo.setFirst(true);
        }

        this.digUnionUserMap.put(unionUid, digUserInfo);
    }

    public boolean containUnionDig(String unionUid) {
        return this.digUnionUserMap.containsKey(unionUid);
    }

    public synchronized long acquireUnionDigUser(String unionUid) {
        DigUserInfo digUserInfo = this.digUnionUserMap.get(unionUid);
        if (digUserInfo == null) {
            return 0;
        }
        return digUserInfo.getUserId();
    }

    public Map<String, DigUserInfo> getDigUnionUserMap() {
        return digUnionUserMap;
    }

    public void setDigUnionUserMap(Map<String, DigUserInfo> digUnionUserMap) {
        this.digUnionUserMap = digUnionUserMap;
    }

    public long acquireDigUser() {
        for (DigUserInfo digUserInfo : this.digUnionUserMap.values()) {
            if (digUserInfo.isFirst()) {
                return digUserInfo.getUserId();
            }
        }
        return 0;
    }

    public PositionInfo acquireEventInfo(long userId) {
        PositionInfo positionInfo = this.eventInfoMap.get(userId);
        if (positionInfo != null) {
            return positionInfo;
        }
        return new PositionInfo();
    }

    public Lock getLock() {
        return lock;
    }

    public int getGroupId() {
        return groupId;
    }

    public void setGroupId(int groupId) {
        this.groupId = groupId;
    }

    public void addOperationTime(long userId, long time) {
        this.operationTimeMap.put(userId, time);
    }

    public boolean checkOperationTimeInCd(long userId,long cd) {
        if (!this.operationTimeMap.containsKey(userId)){
            return false;
        }

        long lastTime = operationTimeMap.get(userId);
        if (System.currentTimeMillis() - lastTime > cd) {
            return false;
        }
        return true;
    }

    public long getLastOperateTime(long userId){
        if (this.operationTimeMap.containsKey(userId)){
            return operationTimeMap.get(userId);
        }else {
            return 0;
        }
    }

}
